package edu.bu.cs673.superkids123.children.controller.games;


import java.util.List;
import java.util.Map;

import javax.swing.ImageIcon;

import edu.bu.cs673.superkids123.AbstractFrame;
import edu.bu.cs673.superkids123.children.DataObjectAccess.LessonGameManager;
import edu.bu.cs673.superkids123.children.controller.AbstractGameController;
import edu.bu.cs673.superkids123.children.model.Game;
import edu.bu.cs673.superkids123.children.model.NumberMatchingGameAnswerProvider;
import edu.bu.cs673.superkids123.children.model.resources.AudioPlayer;
import edu.bu.cs673.superkids123.children.model.resources.ChildrenResource;
import edu.bu.cs673.superkids123.children.model.resources.ChildrenResourceProvider;
import edu.bu.cs673.superkids123.children.view.games.GameResultsView;
import edu.bu.cs673.superkids123.children.view.games.NumberMatchingGameView;


/**
 * NumberMatchingGameController
 * @author David Bardwell
 * @author Adam Phung
 */

public class NumberMatchingGameController extends  AbstractGameController {

	private static final int POINTS_PER_QUESTION = 10;
	private int currentQuestion = 1;
	private Map<Integer, int[]> numberChoicesMap;
	private Map<Integer, int[]> imageChoicesMap;
	private Map<Integer, Integer> correctNumberAnswerMap;
	private Map<Integer, Integer> correctImageAnswerMap;
	ChildrenResourceProvider provider = ChildrenResourceProvider.getInstance();
	private GameResultsController resultsController;	
	private boolean isBusy = false;
	private boolean correctFirstTry = true;
	
	
	public NumberMatchingGameController(AbstractFrame mainFrame) {
		super(mainFrame);
		resultsController = getMainFrame().getController( GameResultsController.class );
	}

	public void startGame() {
		resultsController.notifyResultsController("Number Matching Game");
		resetAnswersForNextGame();
		
		// Start Stat Recording
		List<Game> games = LessonGameManager.getAllActiveGames();
		for (Game game : games) {
			if (game.getName().contains("Match"))
				start(game);
		}
		
		getMainFrame().changeView(NumberMatchingGameView.class);
	}
	
	/**
	 * Ends the game and saves the result.
	 * pass true if entire game was completed
	 * pass false if game is only partially complete, records in db at "Incomplete"
	 * @param complete
	 */
	public void endGame(boolean complete) {
       	if (isActive()) {
       		int score = resultsController.getCorrect() * POINTS_PER_QUESTION;
       		stop(complete, score);
       	}
       	
		if (complete) {
       		getMainFrame().getController(GameResultsController.class)
       			.showResultsScreen(this.getEarnedAchievements());
		}
	}
	
	public int getCurrentQuestionNumber() {
		return currentQuestion;
	}
	
	public void resetAnswersForNextGame() {
		currentQuestion = 1;
		
		// Get answers for number match game for numbers
		NumberMatchingGameAnswerProvider numberAnswerProvider =
			new NumberMatchingGameAnswerProvider(5);
			
		numberAnswerProvider.generateRandomAnswers();
		numberChoicesMap = numberAnswerProvider.getAnswerSelections();
		correctNumberAnswerMap = numberAnswerProvider.getCorrectAnswers();
		
		// Get answers for number matching game for images
		NumberMatchingGameAnswerProvider imageAnswerProvider =
			new NumberMatchingGameAnswerProvider(3);
				
		imageAnswerProvider.generateRandomAnswers();
		imageChoicesMap = imageAnswerProvider.getAnswerSelections();
		correctImageAnswerMap = imageAnswerProvider.getCorrectAnswers();
		
	}
	
	public int[] getPossibleNumberAnswers() {
		return numberChoicesMap.get(currentQuestion);
	}
	
	public int[] getPossibleImageAnswers() {
		return imageChoicesMap.get(currentQuestion);
	}
	
	public ImageIcon getNumberImage() {
		ImageIcon numberImage = null;
		if (currentQuestion < 10) {
			numberImage = provider.getImage(ChildrenResource.NUMBER_IMAGE_MAP.get(currentQuestion));
		}
		else {
			numberImage = provider.getScaledImage(ChildrenResource.NUMBER_IMAGE_MAP.get(currentQuestion), 1.33f);
		}
		return numberImage;
	}
	
	public ImageIcon getGraphicImage() {
		ImageIcon graphicImage = null;
		
		switch (currentQuestion) {
		case 1:
			graphicImage = provider.getImage(ChildrenResource.imageMatch1);
		    break;
		case 2:
			graphicImage = provider.getImage(ChildrenResource.imageMatch2);
		    break;
		case 4:
			graphicImage = provider.getImage(ChildrenResource.imageMatch4);
			break;
		case 6:
			graphicImage = provider.getImage(ChildrenResource.imageMatch6);
			break;
		case 8:
			graphicImage = provider.getImage(ChildrenResource.imageMatch8);
			break;
		}
		return graphicImage;
	}
	
	public void answerButtonPressed(NumberMatchingGameView view, int buttonIndex) {
		if (isBusy) 
			return;
		
		isBusy = true;
		processSelection(view, buttonIndex);
	}
	
	/**
	 *   Process the selection from the child user. Two matching games are 
	 *   intermixed so determine which game is being played and if the child
	 *   selected the correct answer or not. A correct answer causes a short
	 *   congratulations audio message to be played and causes the next question
	 *   to be shown. An incorrect answer causes a short try again audio message
	 *   and keeps the child on the same question to try again.
	 * @param view - NumberMatchingGameView
	 * @param buttonIndex - index of the Answer button selected
	 */
	public void processSelection(NumberMatchingGameView view, int buttonIndex) {
		final NumberMatchingGameView view2 = view;
		final int buttonIndex2 = buttonIndex;
	
		Thread processSelectionThread = new Thread() {
			public void run() {
				int correctAnswer = 0;
				if (currentQuestion == 10 || currentQuestion % 2 == 1) {
					correctAnswer = correctNumberAnswerMap.get(currentQuestion);					
				}
				else {
					correctAnswer = correctImageAnswerMap.get(currentQuestion);
				}

				AudioPlayer audioPlayer = new AudioPlayer();
				
				if (buttonIndex2 == correctAnswer) {
					if (correctFirstTry == true) { 
					    resultsController.correct++;					    
					}    
					else correctFirstTry = true;
					
					view2.updateMessage("Correct - Very Good!");
					byte[] audioData = provider.getAudioContent(ChildrenResource.audioCorrect); 
					audioPlayer.playAudio(audioData);
					try {
						Thread.sleep(100);
					}
					catch (InterruptedException ie) {
						System.out.println("Thread interrupted");
					}
				    view2.updateMessage("Select the correct answer");
				    currentQuestion++;
				    if (currentQuestion <= 10) {
				        //view2.displayNextQuestion(choicesMap.get(currentQuestion));
						if (currentQuestion == 10 || currentQuestion % 2 == 1) {
							view2.displayNextQuestion(numberChoicesMap.get(currentQuestion));					
						}
						else {
							view2.displayNextQuestion(imageChoicesMap.get(currentQuestion));
						}
				    }
				    else {
				    	// go to the game results screen
				    	isBusy = false;
				    	endGame(true);
				    }
				}
				else {
					correctFirstTry = false;
					view2.updateMessage("Sorry, try again.");
					byte[] audioData = provider.getAudioContent(ChildrenResource.audioTryAgain); 
					audioPlayer.playAudio(audioData);
					try {
						Thread.sleep(100);
					}
					catch (InterruptedException ie) {
						System.out.println("Thread interrupted");
					}
					
					view2.updateMessage("Select the correct answer");
				}
				isBusy = false;
			}
		};
		processSelectionThread.start();
		}
}
